﻿using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using SFmpqapi;
using BLP2API;
using System.Diagnostics;
using System.Text.RegularExpressions;
using System.Linq;
using System.Threading.Tasks;

namespace PACKETPARSERMAX20.WinUI
{
    /// <summary>
    /// Summary description for Form1.
    /// </summary>
    /// 

    public class frmViewer : System.Windows.Forms.Form
    {
        private class clsMinimap
        {
            public string filename = null;
            public Texture texture = null;
            public bool cache = false;
            public bool dxt1 = false;
        }

        private class clsArea
        {
            public string area = "";
            public clsMinimap[,] minimaps = new clsMinimap[64, 64];
        }



        // Our global variables for this project
        Device device = null; // Our rendering device
        VertexBuffer vbMonster = null;
        VertexBuffer vbPlayer = null;
        VertexBuffer vbWeed = null;
        VertexBuffer vbMine = null;
        VertexBuffer vbObject = null;
        VertexBuffer vbMinimap = null;
        Microsoft.DirectX.Direct3D.Font font;

        // From WoW
        float mapSize = ((64 * 16) * ((150.0f / 36.0f) * 8));
        float tileSize = 150.0f / 36.0f * 8 * 16;

        float scale = 2;
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.Container components = null;

        public frmViewer()
        {
            InitializeComponent();
            InitializeGraphics();
        }
        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (components != null)
                {
                    components.Dispose();
                }
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code
        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.SuspendLayout();
            // 
            // frmViewer
            // 
            this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
            this.BackColor = System.Drawing.Color.Black;
            this.ClientSize = new System.Drawing.Size(300, 300);
            this.KeyPreview = true;
            this.Name = "frmViewer";
            this.Load += new System.EventHandler(this.frmMain_Load);
            this.ResizeBegin += new System.EventHandler(this.frmViewer_ResizeBegin);
            this.Closing += new System.ComponentModel.CancelEventHandler(this.frmMain_Closing);
            this.ResizeEnd += new System.EventHandler(this.frmViewer_ResizeEnd);
            this.ResumeLayout(false);

        }
        #endregion

        private delegate void DelUpdateText();

        private ArrayList minimapCache = new ArrayList();
        private Hashtable areas = new Hashtable();

        public clsSettings settings;


        private bool mUpdating = false;
        private bool mResizing = false;
        #region "Viewer Methods and Functions"
        public bool InitializeGraphics()
        {
            try
            {
                // Now let's setup our D3D stuff
                PresentParameters presentParams = new PresentParameters();
                presentParams.Windowed = true;
                presentParams.SwapEffect = SwapEffect.Discard;

                device = new Device(0, DeviceType.Hardware, this, CreateFlags.SoftwareVertexProcessing, presentParams);
                device.DeviceReset += new System.EventHandler(this.OnResetDevice);
                this.OnCreateDevice(device, null);
                this.OnResetDevice(device, null);

                //font = new Microsoft.DirectX.Direct3D.Font(device, new System.Drawing.Font("Verdana", 8f));
                font = new Microsoft.DirectX.Direct3D.Font(device, new System.Drawing.Font("Arial", 8f));

                return true;
            }
            catch (DirectXException)
            {
                return false;
            }

        }
        public void OnCreateDevice(object sender, EventArgs e)
        {
            Device dev = (Device)sender;

            // Now Create the VB
            vbMonster = new VertexBuffer(typeof(CustomVertex.PositionColored), 3, dev, 0, CustomVertex.PositionColored.Format, Pool.Default);
            vbMonster.Created += new System.EventHandler(this.OnCreateVBMonster);
            this.OnCreateVBMonster(vbMonster, null);

            // Now Create the VB
            vbPlayer = new VertexBuffer(typeof(CustomVertex.PositionColored), 6, dev, 0, CustomVertex.PositionColored.Format, Pool.Default);
            vbPlayer.Created += new System.EventHandler(this.OnCreateVBPlayer);
            this.OnCreateVBPlayer(vbPlayer, null);

            // Now Create the VB
            vbWeed = new VertexBuffer(typeof(CustomVertex.PositionColored), 12, dev, 0, CustomVertex.PositionColored.Format, Pool.Default);
            vbWeed.Created += new System.EventHandler(this.OnCreateVBWeed);
            this.OnCreateVBWeed(vbWeed, null);

            // Now Create the VB
            vbMine = new VertexBuffer(typeof(CustomVertex.PositionColored), 15, dev, 0, CustomVertex.PositionColored.Format, Pool.Default);
            vbMine.Created += new System.EventHandler(this.OnCreateVBMine);
            this.OnCreateVBMine(vbMine, null);

            // Now Create the VB
            vbObject = new VertexBuffer(typeof(CustomVertex.PositionColored), 6, dev, 0, CustomVertex.PositionColored.Format, Pool.Default);
            vbObject.Created += new System.EventHandler(this.OnCreateVBObject);
            this.OnCreateVBObject(vbObject, null);

            // Now Create the VB
            vbMinimap = new VertexBuffer(typeof(CustomVertex.PositionNormalTextured), 6, dev, 0, CustomVertex.PositionNormalTextured.Format, Pool.Default);
            vbMinimap.Created += new System.EventHandler(this.OnCreateVBMinimap);
            this.OnCreateVBMinimap(vbMinimap, null);
        }
        public void OnResetDevice(object sender, EventArgs e)
        {
            Device dev = (Device)sender;

            // Turn off culling, so we see the front and back of the triangle
            dev.RenderState.CullMode = Cull.None;

            // Turn off D3D lighting, since we are providing our own vertex colors
            dev.RenderState.Lighting = false;

            // Turn on the ZBuffer
            dev.RenderState.ZBufferEnable = true;

            dev.RenderState.AntiAliasedLineEnable = true;
        }
        private Vector3 ComputeNormal(Vector3 v1, Vector3 v2, Vector3 v3)
        {
            Vector3 N = Vector3.Cross(Vector3.Subtract(v2, v1), Vector3.Subtract(v3, v1));
            return Vector3.Normalize(N);
        }
        public void OnCreateVBMinimap(object sender, EventArgs e)
        {
            VertexBuffer vb = (VertexBuffer)sender;
            CustomVertex.PositionNormalTextured[] verts = (CustomVertex.PositionNormalTextured[])vb.Lock(0, 0);

            Vector3 v1 = new Vector3(-((float)(tileSize) / 2), -((float)(tileSize) / 2), 0);
            Vector3 v2 = new Vector3(((float)(tileSize) / 2), -((float)(tileSize) / 2), 0);
            Vector3 v3 = new Vector3(-((float)(tileSize) / 2), ((float)(tileSize) / 2), 0);
            Vector3 n = ComputeNormal(v1, v2, v3);

            verts[0] = new CustomVertex.PositionNormalTextured(v1, n, 0, 0);
            verts[1] = new CustomVertex.PositionNormalTextured(v2, n, 1, 0);
            verts[2] = new CustomVertex.PositionNormalTextured(v3, n, 0, 1);

            v1 = new Vector3(((float)(tileSize) / 2), ((float)(tileSize) / 2), 0);
            v2 = new Vector3(-((float)(tileSize) / 2), ((float)(tileSize) / 2), 0);
            v3 = new Vector3(((float)(tileSize) / 2), -((float)(tileSize) / 2), 0);
            n = ComputeNormal(v1, v2, v3);
            verts[3] = new CustomVertex.PositionNormalTextured(v1, n, 1, 1);
            verts[4] = new CustomVertex.PositionNormalTextured(v2, n, 0, 1);
            verts[5] = new CustomVertex.PositionNormalTextured(v3, n, 1, 0);

            vb.Unlock();
        }
        public void OnCreateVBObject(object sender, EventArgs e)
        {
            VertexBuffer vb = (VertexBuffer)sender;
            CustomVertex.PositionColored[] verts = (CustomVertex.PositionColored[])vb.Lock(0, 0);

            verts[0].X = -1.0f; verts[0].Y = -1.0f; verts[0].Z = 0f; verts[0].Color = System.Drawing.Color.White.ToArgb();
            verts[1].X = 1.0f; verts[1].Y = -1.0f; verts[1].Z = 0f; verts[1].Color = System.Drawing.Color.White.ToArgb();
            verts[2].X = -1.0f; verts[2].Y = 1.0f; verts[2].Z = 0f; verts[2].Color = System.Drawing.Color.White.ToArgb();

            verts[3].X = 1.0f; verts[3].Y = 1.0f; verts[3].Z = 0f; verts[3].Color = System.Drawing.Color.White.ToArgb();
            verts[4].X = 1.0f; verts[4].Y = -1.0f; verts[4].Z = 0f; verts[4].Color = System.Drawing.Color.White.ToArgb();
            verts[5].X = -1.0f; verts[5].Y = 1.0f; verts[5].Z = 0f; verts[5].Color = System.Drawing.Color.White.ToArgb();

            vb.Unlock();
        }
        public void OnCreateVBMine(object sender, EventArgs e)
        {
            VertexBuffer vb = (VertexBuffer)sender;
            CustomVertex.PositionColored[] verts = (CustomVertex.PositionColored[])vb.Lock(0, 0);

            verts[0].X = -2.0f; verts[0].Y = 0.0f; verts[0].Z = 0f; verts[0].Color = System.Drawing.Color.White.ToArgb();
            verts[1].X = -2.0f; verts[1].Y = 1.0f; verts[1].Z = 0f; verts[1].Color = System.Drawing.Color.White.ToArgb();
            verts[2].X = 0.0f; verts[2].Y = 0.0f; verts[2].Z = 0f; verts[2].Color = System.Drawing.Color.White.ToArgb();

            verts[3].X = 2.0f; verts[3].Y = 0.0f; verts[3].Z = 0f; verts[3].Color = System.Drawing.Color.White.ToArgb();
            verts[4].X = 2.0f; verts[4].Y = 1.0f; verts[4].Z = 0f; verts[4].Color = System.Drawing.Color.White.ToArgb();
            verts[5].X = 0.0f; verts[5].Y = 0.0f; verts[5].Z = 0f; verts[5].Color = System.Drawing.Color.White.ToArgb();

            verts[6].X = 2.0f; verts[6].Y = 1.0f; verts[6].Z = 0f; verts[6].Color = System.Drawing.Color.White.ToArgb();
            verts[7].X = 1.0f; verts[7].Y = 2.0f; verts[7].Z = 0f; verts[7].Color = System.Drawing.Color.White.ToArgb();
            verts[8].X = 0.0f; verts[8].Y = 0.0f; verts[8].Z = 0f; verts[8].Color = System.Drawing.Color.White.ToArgb();

            verts[9].X = -2.0f; verts[9].Y = 1.0f; verts[9].Z = 0f; verts[9].Color = System.Drawing.Color.White.ToArgb();
            verts[10].X = -1.0f; verts[10].Y = 2.0f; verts[10].Z = 0f; verts[10].Color = System.Drawing.Color.White.ToArgb();
            verts[11].X = 0.0f; verts[11].Y = 0.0f; verts[11].Z = 0f; verts[11].Color = System.Drawing.Color.White.ToArgb();

            verts[12].X = -1.0f; verts[12].Y = 2.0f; verts[12].Z = 0f; verts[12].Color = System.Drawing.Color.White.ToArgb();
            verts[13].X = 1.0f; verts[13].Y = 2.0f; verts[13].Z = 0f; verts[13].Color = System.Drawing.Color.White.ToArgb();
            verts[14].X = 0.0f; verts[14].Y = 0.0f; verts[14].Z = 0f; verts[14].Color = System.Drawing.Color.White.ToArgb();

            vb.Unlock();
        }
        public void OnCreateVBWeed(object sender, EventArgs e)
        {
            VertexBuffer vb = (VertexBuffer)sender;
            CustomVertex.PositionColored[] verts = (CustomVertex.PositionColored[])vb.Lock(0, 0);

            verts[0].X = 0.0f; verts[0].Y = 2.0f; verts[0].Z = 0f; verts[0].Color = System.Drawing.Color.White.ToArgb();
            verts[1].X = -1.0f; verts[1].Y = 0.0f; verts[1].Z = 0f; verts[1].Color = System.Drawing.Color.White.ToArgb();
            verts[2].X = 1.0f; verts[2].Y = 0.0f; verts[2].Z = 0f; verts[2].Color = System.Drawing.Color.White.ToArgb();

            verts[3].X = 0.0f; verts[3].Y = -2.0f; verts[3].Z = 0f; verts[3].Color = System.Drawing.Color.White.ToArgb();
            verts[4].X = -1.0f; verts[4].Y = 0.0f; verts[4].Z = 0f; verts[4].Color = System.Drawing.Color.White.ToArgb();
            verts[5].X = 1.0f; verts[5].Y = 0.0f; verts[5].Z = 0f; verts[5].Color = System.Drawing.Color.White.ToArgb();

            verts[6].X = -2.0f; verts[6].Y = 0.0f; verts[6].Z = 0f; verts[6].Color = System.Drawing.Color.White.ToArgb();
            verts[7].X = 0.0f; verts[7].Y = 1.0f; verts[7].Z = 0f; verts[7].Color = System.Drawing.Color.White.ToArgb();
            verts[8].X = 0.0f; verts[8].Y = -1.0f; verts[8].Z = 0f; verts[8].Color = System.Drawing.Color.White.ToArgb();

            verts[9].X = 2.0f; verts[9].Y = 0.0f; verts[9].Z = 0f; verts[9].Color = System.Drawing.Color.White.ToArgb();
            verts[10].X = 0.0f; verts[10].Y = 1.0f; verts[10].Z = 0f; verts[10].Color = System.Drawing.Color.White.ToArgb();
            verts[11].X = 0.0f; verts[11].Y = -1.0f; verts[11].Z = 0f; verts[11].Color = System.Drawing.Color.White.ToArgb();

            vb.Unlock();
        }
        public void OnCreateVBPlayer(object sender, EventArgs e)
        {
            VertexBuffer vb = (VertexBuffer)sender;
            CustomVertex.PositionColored[] verts = (CustomVertex.PositionColored[])vb.Lock(0, 0);

            verts[0].X = -2.0f; verts[0].Y = -2.0f; verts[0].Z = 0f; verts[0].Color = System.Drawing.Color.White.ToArgb();
            verts[1].X = 0.0f; verts[1].Y = -1.0f; verts[1].Z = 0f; verts[1].Color = System.Drawing.Color.White.ToArgb();
            verts[2].X = 0.0f; verts[2].Y = 2.0f; verts[2].Z = 0f; verts[2].Color = System.Drawing.Color.White.ToArgb();

            verts[3].X = 2.0f; verts[3].Y = -2.0f; verts[3].Z = 0f; verts[3].Color = System.Drawing.Color.White.ToArgb();
            verts[4].X = 0.0f; verts[4].Y = -1.0f; verts[4].Z = 0f; verts[4].Color = System.Drawing.Color.White.ToArgb();
            verts[5].X = 0.0f; verts[5].Y = 2.0f; verts[5].Z = 0f; verts[5].Color = System.Drawing.Color.White.ToArgb();

            vb.Unlock();
        }
        public void OnCreateVBMonster(object sender, EventArgs e)
        {
            VertexBuffer vb = (VertexBuffer)sender;
            CustomVertex.PositionColored[] verts = (CustomVertex.PositionColored[])vb.Lock(0, 0);

            verts[0].X = -1.0f; verts[0].Y = -2.0f; verts[0].Z = 0f; verts[0].Color = System.Drawing.Color.White.ToArgb();
            verts[1].X = 1.0f; verts[1].Y = -2.0f; verts[1].Z = 0f; verts[1].Color = System.Drawing.Color.White.ToArgb();
            verts[2].X = 0.0f; verts[2].Y = 2.0f; verts[2].Z = 0f; verts[2].Color = System.Drawing.Color.White.ToArgb();

            vb.Unlock();
        }
        #endregion
        private bool mbool = true;

        private void frmMain_Load(object sender, EventArgs e)
        {
            settings = new clsSettings();
            settings.LoadDefaults();
            settings.UpdateHashtable();
            this.TopMost = settings.StayOnTop;
            BuildAreas();
        }


        private void frmMain_Closing(object sender, CancelEventArgs e)
        {

            settings.FormX = Left;
            settings.FormY = Top;
            settings.FormWidth = Width;
            settings.FormHeight = Height;

            XmlTextWriter xw = new XmlTextWriter("SERFLITEMAX20.Viewer.xml", System.Text.Encoding.ASCII);
            XmlSerializer xs = new XmlSerializer(settings.GetType());
            xs.Serialize(xw, settings);
            xw.Close();
        }

        public void UpdateViewer(object sender)
        {
            if (!StaticObjects.RefreshRadar) { return; }
            //this.InvokeRequired 
            if (sender is PACKETPARSERMAX20.CORE.WoWCore)
            {
                //var start = DateTime.Now;
                OnUpdateMain((PACKETPARSERMAX20.CORE.WoWCore)sender);
                //System.Diagnostics.Debug.WriteLine(string.Format("{0} took {1}.", "viewer", DateTime.Now - start));

            }
        }

        private object lockfont = new object();

        private void OnUpdateMain(PACKETPARSERMAX20.CORE.WoWCore core)
        {
            if (!mResizing)
            {
                if (!mUpdating)
                {
                    if (device == null)
                        return;

                    if (core.Player == null)
                        return;


                    mUpdating = true;

                    try
                    {
                        //Clear the backbuffer to a black color
                        device.Clear(ClearFlags.Target, System.Drawing.Color.Black, 1.0f, 0);

                        var camDist = 100000.0F;
                        var camPos = new Vector3(0.0F, 0.0F, camDist);
                        var camTarg = new Vector3(0.0F, 0.0F, 0.0F);
                        var camUpVec = new Vector3(0.0F, -1.0F, 0.0F);

                        Matrix rotMap = Matrix.RotationY(180 * 0.01745329f) * Matrix.RotationX(180 * 0.01745329f);

                        if (settings.RotateMap)
                            rotMap *= Matrix.RotationZ(360 * 0.01745329f - core.Player.O);

                        camPos.TransformCoordinate(rotMap);
                        camTarg.TransformCoordinate(rotMap);
                        camUpVec.TransformCoordinate(rotMap);

                        camTarg.Add(new Vector3(core.Player.Y, core.Player.X, core.Player.Z));
                        camPos.Add(new Vector3(core.Player.Y, core.Player.X, core.Player.Z));

                        device.Transform.View = Matrix.LookAtLH(camPos, camTarg, camUpVec);
                        device.Transform.Projection = Matrix.PerspectiveLH(Width / (camDist * scale), Height / (camDist * scale), 1, 1000000);

                        device.BeginScene();

                        if (mbool && settings.ShowMinimap)
                        {
                            DrawMinimap(core.Player.Y, core.Player.X, (int)core.MapID);
                        }
 
                        var list = core.ObjList.Values.Where(t => (t.TypeID == PACKETPARSERMAX20.CORE.TypeID.TYPEID_DYNAMICOBJECT ||
                                    t.TypeID == PACKETPARSERMAX20.CORE.TypeID.TYPEID_UNIT ||
                                    t.TypeID == PACKETPARSERMAX20.CORE.TypeID.TYPEID_PLAYER ||
                                    t.TypeID == PACKETPARSERMAX20.CORE.TypeID.TYPEID_GAMEOBJECT ||
                                    t.TypeID == PACKETPARSERMAX20.CORE.TypeID.TYPEID_CORPSE) && t.HasPosition());

                        foreach (var obj in list)
                        {


                            int tcolor = Color.White.ToArgb();
                            bool rotate = true;
                            int noVertexs = 4;
                            VertexBuffer vBuffer = vbObject;
                            string name = obj.Name;


                            if (obj is PACKETPARSERMAX20.CORE.WoWObjectCorpse)
                            {
                                name = "Corpse Of " + name;
                                tcolor = Color.LightGray.ToArgb();
                            }
                            else if (obj is PACKETPARSERMAX20.CORE.WoWObjectPlayer)
                            {
                                PACKETPARSERMAX20.CORE.WoWObjectPlayer objPlayer = (PACKETPARSERMAX20.CORE.WoWObjectPlayer)obj;

                                vBuffer = vbPlayer;

                                switch (objPlayer.GetObjectReactionToPlayer())
                                {
                                    case PACKETPARSERMAX20.CORE.ObjectReaction.PLAYER_FREINDLY:
                                        {
                                            tcolor = Color.White.ToArgb();
                                        } break;
                                    case PACKETPARSERMAX20.CORE.ObjectReaction.PLAYER_ENEMY_FLAGED:
                                        {
                                            tcolor = Color.OrangeRed.ToArgb();
                                        } break;
                                    case PACKETPARSERMAX20.CORE.ObjectReaction.PLAYER_ENEMY_UNFLAGED:
                                        {
                                            tcolor = Color.Orange.ToArgb();
                                        } break;
                                }

                            }
                            else if (obj is PACKETPARSERMAX20.CORE.WoWObjectUnit)
                            {
                                PACKETPARSERMAX20.CORE.WoWObjectUnit objUnit = (PACKETPARSERMAX20.CORE.WoWObjectUnit)obj;

                                vBuffer = vbMonster;

                                if (objUnit.UNIT_FIELD_HEALTH == 0)
                                {
                                    name = "Corpse Of " + name;
                                    tcolor = Color.LightGray.ToArgb();
                                }
                                else
                                {

                                    tcolor = Color.LightGreen.ToArgb();
                                    switch (objUnit.GetObjectReactionToPlayer())
                                    {
                                        case PACKETPARSERMAX20.CORE.ObjectReaction.UNIT_AGGRESSIVE:
                                            {
                                                tcolor = Color.Red.ToArgb();
                                            } break;
                                        case PACKETPARSERMAX20.CORE.ObjectReaction.UNIT_NEUTRAL:
                                            {
                                                tcolor = Color.Yellow.ToArgb();
                                            } break;
                                        case PACKETPARSERMAX20.CORE.ObjectReaction.UNIT_FREINDLY:
                                            {
                                                tcolor = Color.LightGreen.ToArgb();
                                            } break;
                                        case PACKETPARSERMAX20.CORE.ObjectReaction.UNIT_UNFREINDLY:
                                            {
                                                tcolor = Color.Brown.ToArgb();
                                            } break;
                                    }
                                }


                            }
                            else if (obj.TypeID == PACKETPARSERMAX20.CORE.TypeID.TYPEID_GAMEOBJECT)
                            {
                                vBuffer = vbObject;
                                tcolor = Color.Cyan.ToArgb();
                            }
                            else if (obj.TypeID == PACKETPARSERMAX20.CORE.TypeID.TYPEID_DYNAMICOBJECT)
                            {
                                vBuffer = vbPlayer;
                                tcolor = Color.Red.ToArgb();
                                if (name == null)
                                {
                                    name = obj.SubType.ToString();
                                }
                            }

                            float iscale = 2 * (2 / scale);
                            Vector3 pos = new Vector3(obj.Y, obj.X, obj.Z);

                            device.Transform.World = Matrix.Scaling(iscale, iscale, iscale);

                            if (rotate)
                                device.Transform.World *= Matrix.RotationZ(360 * 0.01745329f - obj.O);
                            else if (settings.RotateMap)
                                device.Transform.World *= Matrix.RotationZ(360 * 0.01745329f - core.Player.O);

                            device.Transform.World *= Matrix.Translation(pos);

                            device.RenderState.TextureFactor = tcolor;

                            device.TextureState[0].ColorOperation = TextureOperation.Modulate;
                            device.TextureState[0].ColorArgument0 = TextureArgument.TextureColor;
                            device.TextureState[0].ColorArgument1 = TextureArgument.TFactor;

                            device.VertexFormat = CustomVertex.PositionColored.Format;
                            device.SetTexture(0, null);

                            device.SetStreamSource(0, vBuffer, 0);
                            device.DrawPrimitives(PrimitiveType.TriangleList, 0, noVertexs);

                            pos = Vector3.Project(new Vector3(0, 0, 0), device.Viewport, device.Transform.Projection, device.Transform.View, device.Transform.World);

                            if (name != null)
                            {
                                font.DrawText(null, name, (int)pos.X + 10, (int)pos.Y - 4, tcolor);
                            }
                        }



                        device.EndScene();
                        device.Present();
                    }
                    catch (Exception exc)
                    {
                        System.Windows.Forms.Application.DoEvents();
                        Console.WriteLine(exc.Message);
                    }


                }
            }

            if (StaticObjects.RadarRefreshRate > 0)
            {
                System.Threading.Thread.Sleep(StaticObjects.RadarRefreshRate);
            }

            mUpdating = false;
        }

        private string GetMapName(int id)
        {
            string area = "";
            switch (id)
            {
                case 0: area = "Azeroth"; break;
                case 1: area = "Kalimdor"; break;
                case 13: area = "test"; break;
                case 25: area = "ScottTest"; break;
                case 29: area = "Test"; break;
                case 30: area = "PVPZone01"; break;
                case 33: area = "Shadowfang"; break;
                case 34: area = "StormwindJail"; break;
                case 35: area = "StormwindPrison"; break;
                case 36: area = "DeadminesInstance"; break;
                case 37: area = "PVPZone02"; break;
                case 42: area = "Collin"; break;
                case 43: area = "WailingCaverns"; break;
                case 44: area = "Monastery"; break;
                case 47: area = "RazorfenKraulInstance"; break;
                case 48: area = "Blackfathom"; break;
                case 70: area = "Uldaman"; break;
                case 90: area = "GnomeragonInstance"; break;
                case 109: area = "SunkenTemple"; break;
                case 129: area = "RazorfenDowns"; break;
                case 169: area = "EmeraldDream"; break;
                case 189: area = "MonasteryInstances"; break;
                case 209: area = "TanarisInstance"; break;
                case 229: area = "BlackRockSpire"; break;
                case 230: area = "BlackrockDepths"; break;
                case 249: area = "OnyxiaLairInstance"; break;
                case 269: area = "CavernsOfTime"; break;
                case 289: area = "SchoolofNecromancy"; break;
                case 309: area = "Zul'gurub"; break;
                case 329: area = "Stratholme"; break;
                case 349: area = "Mauradon"; break;
                case 369: area = "DeeprunTram"; break;
                case 389: area = "OrgrimmarInstance"; break;
                case 409: area = "MoltenCore"; break;
                case 429: area = "DireMaul"; break;
                case 449: area = "AlliancePVPBarracks"; break;
                case 450: area = "HordePVPBarracks"; break;
                case 451: area = "development"; break;
                case 469: area = "BlackwingLair"; break;
                case 489: area = "PVPZone03"; break;
                case 509: area = "AhnQiraj"; break;
                case 529: area = "PVPZone04"; break;
                case 530: area = "Expansion01"; break;
                case 531: area = "AhnQirajTemple"; break;
                case 532: area = "Karazahn"; break;
                case 533: area = "Stratholme Raid"; break;
                case 534: area = "HyjalPast"; break;
                case 540: area = "HellfireMilitary"; break;
                case 542: area = "HellfireDemon"; break;
                case 543: area = "HellfireRampart"; break;
                case 544: area = "HellfireRaid"; break;
                case 545: area = "CoilfangPumping"; break;
                case 546: area = "CoilfangMarsh"; break;
                case 547: area = "CoilfangDraenei"; break;
                case 548: area = "CoilfangRaid"; break;
                case 550: area = "TempestKeepRaid"; break;
                case 552: area = "TempestKeepArcane"; break;
                case 553: area = "TempestKeepAtrium"; break;
                case 554: area = "TempestKeepFactory"; break;
                case 555: area = "AuchindounShadow"; break;
                case 556: area = "AuchindounDemon"; break;
                case 557: area = "AuchindounEthereal"; break;
                case 558: area = "AuchindounDraenei"; break;
                case 559: area = "PVPZone05"; break;
                case 560: area = "HillsbradPast"; break;
                case 562: area = "bladesedgearena"; break;
                case 564: area = "BlackTemple"; break;
                case 565: area = "GruulsLair"; break;
                case 566: area = "NetherstormBG"; break;
                case 568: area = "ZulAman"; break;
                case 571: area = "Northrend"; break;
                case 572: area = "PVPLordaeron"; break;
                case 573: area = "ExteriorTest"; break;
                case 574: area = "Valgarde70"; break;
                case 575: area = "UtgardePinnacle"; break;
                case 576: area = "Nexus70"; break;
                case 578: area = "Nexus80"; break;
                case 580: area = "SunwellPlateau"; break;
                case 582: area = "Transport176244"; break;
                case 584: area = "Transport176231"; break;
                case 585: area = "Sunwell5ManFix"; break;
                case 586: area = "Transport181645"; break;
                case 587: area = "Transport177233"; break;
                case 588: area = "Transport176310"; break;
                case 589: area = "Transport175080"; break;
                case 590: area = "Transport176495"; break;
                case 591: area = "Transport164871"; break;
                case 592: area = "Transport186238"; break;
                case 593: area = "Transport20808"; break;
                case 594: area = "Transport187038"; break;
                case 595: area = "StratholmeCOT"; break;
                case 596: area = "Transport187263"; break;
                case 597: area = "CraigTest"; break;
                case 598: area = "Sunwell5Man"; break;
                case 599: area = "Ulduar70"; break;
                case 600: area = "DrakTheronKeep"; break;
                case 601: area = "Azjol_Uppercity"; break;
                case 602: area = "Ulduar80"; break;
                case 603: area = "UlduarRaid"; break;
                case 604: area = "GunDrak"; break;
                case 605: area = "development_nonweighted"; break;
                case 606: area = "QA_DVD"; break;
                case 607: area = "NorthrendBG"; break;
                case 608: area = "DalaranPrison"; break;
                case 609: area = "DeathKnightStart"; break;
                case 610: area = "Transport_Tirisfal _Vengeance_Landing"; break;
                case 612: area = "Transport_Menethil_Valgarde"; break;
                case 613: area = "Transport_Orgrimmar_Warsong_Hold"; break;
                case 614: area = "Transport_Stormwind_Valiance_Keep"; break;
                case 615: area = "ChamberOfAspectsBlack"; break;
                case 616: area = "NexusRaid"; break;
                case 617: area = "DalaranArena"; break;
                case 618: area = "OrgrimmarArena"; break;
                case 619: area = "Azjol_LowerCity"; break;
                case 620: area = "Transport_Moa'ki_Unu'pe"; break;
                case 621: area = "Transport_Moa'ki_Kamagua"; break;
                case 622: area = "Transport192241"; break;
                case 623: area = "Transport192242"; break;
                case 624: area = "WintergraspRaid"; break;

            }
            return area;
        }

        private void DrawMinimap(float PosX, float PosY, int mapid)
        {
            try
            {
                float absCoordX = (mapSize / 2) - PosX + tileSize;
                float absCoordY = (mapSize / 2) - PosY + tileSize;

                int tileX = (int)(absCoordX / tileSize) - 1;
                int tileY = (int)(absCoordY / tileSize) - 1;

                foreach (clsMinimap minimap in minimapCache)
                    minimap.cache = false;


                string area = GetMapName(mapid);


                for (int x = tileX - settings.MinimapRadius; x <= (tileX + settings.MinimapRadius); x++)
                    for (int y = tileY - settings.MinimapRadius; y <= (tileY + settings.MinimapRadius); y++)
                    {
                        clsMinimap minimap = LoadMinimap(x, y, area);

                        if (minimap == null)
                            continue;

                        minimap.cache = true;
                        if (minimap.texture != null)
                        {
                            float mapX = -((x * tileSize) - (mapSize / 2)) - (tileSize / 2);
                            float mapY = -((y * tileSize) - (mapSize / 2)) - (tileSize / 2);

                            if (minimap.dxt1)
                                device.Transform.World = Matrix.RotationX(180 * 0.01745329f) * Matrix.RotationY(180 * 0.01745329f) * Matrix.Translation(mapX, mapY, -1000);
                            else
                                device.Transform.World = Matrix.RotationY(180 * 0.01745329f) * Matrix.Translation(mapX, mapY, -1000);

                            device.SetTexture(0, minimap.texture);
                            device.TextureState[0].ColorOperation = TextureOperation.Modulate;
                            device.TextureState[0].ColorArgument1 = TextureArgument.TextureColor;
                            device.TextureState[0].ColorArgument2 = TextureArgument.Diffuse;
                            device.TextureState[0].AlphaOperation = TextureOperation.Disable;

                            device.VertexFormat = CustomVertex.PositionNormalTextured.Format;

                            device.SetStreamSource(0, vbMinimap, 0);
                            device.DrawPrimitives(PrimitiveType.TriangleList, 0, 2);
                        }
                    }

                foreach (clsMinimap minimap in minimapCache)
                    if (!minimap.cache)
                    {
                        // Dont cache it anymore
                        if (minimap.texture != null)
                        {
                            minimap.texture.Dispose();
                            minimap.texture = null;
                        }
                    }
            }
            catch (Exception exc)
            {
                Console.WriteLine(exc.Message);
            }
        }

        private void GetMinimapTexture(clsMinimap minimap)
        {
            int hMPQ = 0;
            int hFile = 0;
            int FileSize = 0;
            int FileRead = 0;
            //"C:\\Program Files\\World of Warcraft\\Data\\texture.MPQ"
            string path = ".\\minimap.MPQ";
            if (!System.IO.File.Exists(path)) { path = @"H:\DATA\MPQ\minimap.MPQ"; }
            if (SFmpq.SFileOpenArchive(path, 0, 0, ref hMPQ) != 1)
            {
                return;
            }

            //if( SFmpq.SFileOpenFileEx( hMPQ, "textures\\Minimap\\" + minimap.filename, 0, ref hFile) != 1)
            if (SFmpq.SFileOpenFileEx(hMPQ, minimap.filename, 0, ref hFile) != 1)
            {
                SFmpq.SFileCloseFile(hMPQ);
                return;
            }

            FileSize = SFmpq.SFileGetFileSize(hFile, ref FileSize);
            byte[] buffer = new byte[FileSize];

            //WoW.LogLine( "Reading texture.MPQ|textures\\Minimap\\{0}", minimap.filename);
            if (SFmpq.SFileReadFile(hFile, buffer, (uint)FileSize, ref FileRead, IntPtr.Zero) == 1)
            {
                //WoW.LogLine( "Parsing texture.MPQ|textures\\Minimap\\{0}", minimap.filename);

                minimap.dxt1 = true;
                MemoryStream ms = BLP2Parse.BLPtoDXT1(buffer);
                if (ms != null && ms.Length > 0x70)
                {
                    ms.Seek(0, SeekOrigin.Begin);
                    try
                    {
                        minimap.texture = TextureLoader.FromStream(device, ms);
                        if (minimap.texture == null)
                            minimap.dxt1 = false;
                    }
                    catch
                    {
                        minimap.dxt1 = false;
                    }
                }

                if (!minimap.dxt1)
                {
                    ms = BLP2Parse.BLPtoTGA(buffer);
                    ms.Seek(0, SeekOrigin.Begin);
                    try
                    {
                        minimap.texture = TextureLoader.FromStream(device, ms);
                    }
                    catch
                    {
                    }
                }
            }
            else
            {
            }

            SFmpq.SFileCloseFile(hFile);
            SFmpq.SFileCloseArchive(hMPQ);

            return;
        }

        private clsMinimap LoadMinimap(int X, int Y, string Area)
        {
            if (X > 63 || Y > 63 || X < 0 || Y < 0)
                return null;

            clsArea area = (clsArea)areas[Area];
            if (area == null)
                return null;

            clsMinimap minimap = area.minimaps[X, Y];
            if (minimap != null && minimap.texture == null)
                GetMinimapTexture(minimap);

            return minimap;
        }

        private void BuildMinimapList(byte[] md5list)
        {
            MemoryStream src = new MemoryStream(md5list);
            StreamReader sr = new StreamReader(src);

            Regex map = new Regex(@"^.[^\\]+\\[a-z,A-Z]+([0-9][0-9])_([0-9][0-9])\.blp[\t, ]+(.+)$");

            clsArea area = null;
            while (sr.Peek() != -1)
            {
                string line = sr.ReadLine();

                if (line.StartsWith("dir: "))
                {
                    if (area != null)
                    {
                        int count = 0;
                        for (int x = 0; x < 64; x++)
                            for (int y = 0; y < 64; y++)
                                if (area.minimaps[x, y] != null)
                                    count++;

                    }

                    // Check if its a zone map, or an indoor map
                    System.Diagnostics.Debug.WriteLine(line);
                    if (line.IndexOf("\\") == -1)
                    {
                        area = new clsArea();
                        area.area = line.Remove(0, 5);
                        areas.Add(area.area, area);
                    }
                    else
                    {
                        area = null;
                    }
                }
                else if (area != null)
                {
                    Match m = map.Match(line);
                    if (m.Success)
                    {
                        int x = int.Parse(m.Groups[1].Value);
                        int y = int.Parse(m.Groups[2].Value);

                        area.minimaps[x, y] = new clsMinimap();
                        area.minimaps[x, y].filename = m.Groups[3].Value;
                    }
                    else
                    {
                        System.Diagnostics.Debug.WriteLine("no match " + line);
                    }
                }
            }
        }

        public void BuildAreas()
        {
            int hMPQ = 0;
            int hFile = 0;
            int FileSize = 0;
            int FileRead = 0;

            areas.Clear();

            //WoW.LogLine( "Opening {0}", path + "\\Data\\misc.MPQ");
            //if( SFmpq.SFileOpenArchive( ".\\misc.MPQ", 0, 0, ref hMPQ) == 1)

            string path = ".\\minimap.MPQ";
            if (!System.IO.File.Exists(path)) { path = @"H:\DATA\MPQ\minimap.MPQ"; }


            if (SFmpq.SFileOpenArchive(path, 0, 0, ref hMPQ) == 1)
            {
                //WoW.LogLine( "Opening misc.MPQ|textures\\Minimap\\md5translate.trs");
                //if( SFmpq.SFileOpenFileEx( hMPQ, "textures\\Minimap\\md5translate.trs", 0, ref hFile) == 1)
                if (SFmpq.SFileOpenFileEx(hMPQ, "md5translate.trs", 0, ref hFile) == 1)
                {
                    FileSize = SFmpq.SFileGetFileSize(hFile, ref FileSize);

                    byte[] buffer = new byte[FileSize];
                    //WoW.LogLine( "Reading misc.MPQ|textures\\Minimap\\md5translate.trs[{0}]", FileSize);
                    if (SFmpq.SFileReadFile(hFile, buffer, (uint)FileSize, ref FileRead, IntPtr.Zero) == 1)
                    {
                        //WoW.LogLine( "Parsing md5translate.trs");
                        BuildMinimapList(buffer);
                    }
                    else
                    {
                    }

                    SFmpq.SFileCloseFile(hFile);
                }
                else
                {

                }

                SFmpq.SFileCloseArchive(hMPQ);
            }
            else
            {

            }
        }

        private void frmViewer_ResizeBegin(object sender, EventArgs e)
        {
            //while (mUpdating)
            // System.Windows.Forms.Application.DoEvents();
            mResizing = true;
        }

        private void frmViewer_ResizeEnd(object sender, EventArgs e)
        {
            mResizing = false;
        }

    }
}
